<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Simplified MongoDB with Panache</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/mongodb-panache" />
  <meta property="og:title" content="Quarkus - Simplified MongoDB with Panache" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/mongodb-panache">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Simplified MongoDB with Panache</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#first-an-example">First: an example</a></li>
<li><a href="#solution">Solution</a></li>
<li><a href="#creating-the-maven-project">Creating the Maven project</a></li>
<li><a href="#setting-up-and-configuring-mongodb-with-panache">Setting up and configuring MongoDB with Panache</a></li>
<li><a href="#solution-1-using-the-active-record-pattern">Solution 1: using the active record pattern</a>
<ul class="sectlevel2">
<li><a href="#defining-your-entity">Defining your entity</a></li>
<li><a href="#most-useful-operations">Most useful operations</a></li>
<li><a href="#adding-entity-methods">Adding entity methods</a></li>
</ul>
</li>
<li><a href="#solution-2-using-the-repository-pattern">Solution 2: using the repository pattern</a>
<ul class="sectlevel2">
<li><a href="#defining-your-entity-2">Defining your entity</a></li>
<li><a href="#defining-your-repository">Defining your repository</a></li>
<li><a href="#most-useful-operations-2">Most useful operations</a></li>
</ul>
</li>
<li><a href="#advanced-query">Advanced Query</a>
<ul class="sectlevel2">
<li><a href="#paging">Paging</a></li>
<li><a href="#using-a-range-instead-of-pages">Using a range instead of pages</a></li>
<li><a href="#sorting">Sorting</a></li>
<li><a href="#simplified-queries">Simplified queries</a></li>
<li><a href="#query-parameters">Query parameters</a></li>
<li><a href="#query-projection">Query projection</a></li>
</ul>
</li>
<li><a href="#query-debugging">Query debugging</a></li>
<li><a href="#transactions">Transactions</a></li>
<li><a href="#custom-ids">Custom IDs</a></li>
<li><a href="#working-with-kotlin-data-classes">Working with Kotlin Data classes</a></li>
<li><a href="#reactive">Reactive Entities and Repositories</a></li>
<li><a href="#mocking">Mocking</a>
<ul class="sectlevel2">
<li><a href="#using-the-active-record-pattern">Using the active-record pattern</a></li>
<li><a href="#using-the-repository-pattern">Using the repository pattern</a></li>
</ul>
</li>
<li><a href="#how-and-why-we-simplify-mongodb-api">How and why we simplify MongoDB API</a></li>
<li><a href="#defining-entities-in-external-projects-or-jars">Defining entities in external projects or jars</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>MongoDB is a well known NoSQL Database that is widely used, but using its raw API can be cumbersome as you need to express your entities and your queries as a MongoDB <a href="https://mongodb.github.io/mongo-java-driver/3.11/bson/documents/#document"><code>Document</code></a>.</p>
</div>
<div class="paragraph">
<p>MongoDB with Panache provides active record style entities (and repositories) like you have in <a href="hibernate-orm-panache">Hibernate ORM with Panache</a> and focuses on making your entities trivial and fun to write in Quarkus.</p>
</div>
<div class="paragraph">
<p>It is built on top of the <a href="mongodb">MongoDB Client</a> extension.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="first-an-example"><a class="anchor" href="#first-an-example"></a>First: an example</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Panache allows you to write your MongoDB entities like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class Person extends PanacheMongoEntity {
    public String name;
    public LocalDate birth;
    public Status status;

    public static Person findByName(String name){
        return find("name", name).firstResult();
    }

    public static List&lt;Person&gt; findAlive(){
        return list("status", Status.Alive);
    }

    public static void deleteLoics(){
        delete("name", "Loïc");
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You have noticed how much more compact and readable the code is compared to using the MongoDB API?
Does this look interesting? Read on!</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
the <code>list()</code> method might be surprising at first. It takes fragments of PanacheQL queries (subset of JPQL) and contextualizes the rest.
That makes for very concise but yet readable code.
MongoDB native queries are also supported.
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
what was described above is essentially the <a href="https://www.martinfowler.com/eaaCatalog/activeRecord.html">active record pattern</a>, sometimes just called the entity pattern.
MongoDB with Panache also allows for the use of the more classical <a href="https://martinfowler.com/eaaCatalog/repository.html">repository pattern</a> via <code>PanacheMongoRepository</code>.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution"><a class="anchor" href="#solution"></a>Solution</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.</p>
</div>
<div class="paragraph">
<p>Clone the Git repository: <code>git clone <a href="https://github.com/quarkusio/quarkus-quickstarts.git" class="bare">https://github.com/quarkusio/quarkus-quickstarts.git</a></code>, or download an <a href="https://github.com/quarkusio/quarkus-quickstarts/archive/master.zip">archive</a>.</p>
</div>
<div class="paragraph">
<p>The solution is located in the <code>mongodb-panache-quickstart</code> <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/mongodb-panache-quickstart">directory</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="creating-the-maven-project"><a class="anchor" href="#creating-the-maven-project"></a>Creating the Maven project</h2>
<div class="sectionbody">
<div class="paragraph">
<p>First, we need a new project. Create a new project with the following command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">mvn io.quarkus:quarkus-maven-plugin:1.7.0.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=mongodb-panache-quickstart \
    -DclassName="org.acme.mongodb.panache.PersonResource" \
    -Dpath="/persons" \
    -Dextensions="resteasy-jsonb,mongodb-panache"
cd mongodb-panache-quickstart</code></pre>
</div>
</div>
<div class="paragraph">
<p>This command generates a Maven structure importing the RESTEasy/JAX-RS, JSON-B and MongoDB with Panache extensions.
After this, the <code>quarkus-mongodb-panache</code> extension has been added to your <code>pom.xml</code>.</p>
</div>
<div class="paragraph">
<p>If you don&#8217;t want to generate a new project, add the dependency in your <code>pom.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-mongodb-panache&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="setting-up-and-configuring-mongodb-with-panache"><a class="anchor" href="#setting-up-and-configuring-mongodb-with-panache"></a>Setting up and configuring MongoDB with Panache</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To get started:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>add your settings in <code>application.properties</code></p>
</li>
<li>
<p>Make your entities extend <code>PanacheMongoEntity</code> (optional if you are using the repository pattern)</p>
</li>
<li>
<p>Optionally, use the <code>@MongoEntity</code> annotation to specify the name of the collection, the name of the database or the name of the client.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Then add the relevant configuration properties in <code>application.properties</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs"># configure the MongoDB client for a replica set of two nodes
quarkus.mongodb.connection-string = mongodb://mongo1:27017,mongo2:27017
# mandatory if you don't specify the name of the database using @MongoEntity
quarkus.mongodb.database = person</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>quarkus.mongodb.database</code> property will be used by MongoDB with Panache to determine the name of the database where your entities will be persisted (if not overridden by <code>@MongoEntity</code>).</p>
</div>
<div class="paragraph">
<p>The <code>@MongoEntity</code> annotation allows configuring:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>the name of the client for multi-tenant application, see <a href="mongodb#multiple-mongodb-clients">Multiple MongoDB Clients</a>. Otherwise, the default client will be used.</p>
</li>
<li>
<p>the name of the database, otherwise, the <code>quarkus.mongodb.database</code> property will be used.</p>
</li>
<li>
<p>the name of the collection, otherwise the simple name of the class will be used.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For advanced configuration of the MongoDB client, you can follow the <a href="mongodb#configuring-the-mongodb-database">Configuring the MongoDB database guide</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution-1-using-the-active-record-pattern"><a class="anchor" href="#solution-1-using-the-active-record-pattern"></a>Solution 1: using the active record pattern</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="defining-your-entity"><a class="anchor" href="#defining-your-entity"></a>Defining your entity</h3>
<div class="paragraph">
<p>To define a Panache entity, simply extend <code>PanacheMongoEntity</code> and add your columns as public fields.
You can add the <code>@MongoEntity</code> annotation to your entity if you need to customize the name of the collection, the database, or the client.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@MongoEntity(collection="ThePerson")
public class Person extends PanacheMongoEntity {
    public String name;

    // will be persisted as a 'birth' field in MongoDB
    @BsonProperty("birth")
    public LocalDate birthDate;

    public Status status;
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Annotating with <code>@MongoEntity</code> is optional. Here the entity will be stored in the <code>ThePerson</code> collection instead of the default <code>Person</code> collection.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>MongoDB with Panache uses the <a href="https://mongodb.github.io/mongo-java-driver/3.11/bson/pojos/">PojoCodecProvider</a> to map your entities to a MongoDB <code>Document</code>.</p>
</div>
<div class="paragraph">
<p>You will be allowed to use the following annotations to customize this mapping:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>@BsonId</code>: allows you to customize the ID field, see <a href="#custom-ids">Custom IDs</a>.</p>
</li>
<li>
<p><code>@BsonProperty</code>: customize the serialized name of the field.</p>
</li>
<li>
<p><code>@BsonIgnore</code>: ignore a field during the serialization.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If you need to write accessors, you can:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class Person extends PanacheMongoEntity {
    public String name;
    public LocalDate birth;
    public Status status;

    // return name as uppercase in the model
    public String getName(){
        return name.toUpperCase();
    }

    // store all names in lowercase in the DB
    public void setName(String name){
        this.name = name.toLowerCase();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>And thanks to our field access rewrite, when your users read <code>person.name</code> they will actually call your <code>getName()</code> accessor, and similarly for field writes and the setter.
This allows for proper encapsulation at runtime as all fields calls will be replaced by the corresponding getter/setter calls.</p>
</div>
</div>
<div class="sect2">
<h3 id="most-useful-operations"><a class="anchor" href="#most-useful-operations"></a>Most useful operations</h3>
<div class="paragraph">
<p>Once you have written your entity, here are the most common operations you will be able to perform:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// creating a person
Person person = new Person();
person.name = "Loïc";
person.birth = LocalDate.of(1910, Month.FEBRUARY, 1);
person.status = Status.Alive;

// persist it
person.persist();

person.status = Status.Dead;

// Your must call update() in order to send your entity modifications to MongoDB
person.update();

// delete it
person.delete();

// getting a list of all Person entities
List&lt;Person&gt; allPersons = Person.listAll();

// finding a specific person by ID
person = Person.findById(personId);

// finding a specific person by ID via an Optional
Optional&lt;Person&gt; optional = Person.findByIdOptional(personId);
person = optional.orElseThrow(() -&gt; new NotFoundException());

// finding all living persons
List&lt;Person&gt; livingPersons = Person.list("status", Status.Alive);

// counting all persons
long countAll = Person.count();

// counting all living persons
long countAlive = Person.count("status", Status.Alive);

// delete all living persons
Person.delete("status", Status.Alive);

// delete all persons
Person.deleteAll();

// delete by id
boolean deleted = Person.deleteById(personId);

// set the name of all living persons to 'Mortal'
long updated = Person.update("name", "Mortal").where("status", Status.Alive);</code></pre>
</div>
</div>
<div class="paragraph">
<p>All <code>list</code> methods have equivalent <code>stream</code> versions.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">Stream&lt;Person&gt; persons = Person.streamAll();
List&lt;String&gt; namesButEmmanuels = persons
    .map(p -&gt; p.name.toLowerCase() )
    .filter( n -&gt; ! "emmanuel".equals(n) )
    .collect(Collectors.toList());</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
A <code>persistOrUpdate()</code> method exist that persist or update an entity in the database, it uses the <em>upsert</em> capability of MongoDB to do it in a single query.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="adding-entity-methods"><a class="anchor" href="#adding-entity-methods"></a>Adding entity methods</h3>
<div class="paragraph">
<p>Add custom queries on your entities inside the entities themselves.
That way, you and your co-workers can find them easily, and queries are co-located with the object they operate on.
Adding them as static methods in your entity class is the Panache Active Record way.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class Person extends PanacheMongoEntity {
    public String name;
    public LocalDate birth;
    public Status status;

    public static Person findByName(String name){
        return find("name", name).firstResult();
    }

    public static List&lt;Person&gt; findAlive(){
        return list("status", Status.Alive);
    }

    public static void deleteLoics(){
        delete("name", "Loïc");
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution-2-using-the-repository-pattern"><a class="anchor" href="#solution-2-using-the-repository-pattern"></a>Solution 2: using the repository pattern</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="defining-your-entity-2"><a class="anchor" href="#defining-your-entity-2"></a>Defining your entity</h3>
<div class="paragraph">
<p>You can define your entity as regular POJO.
You can add the <code>@MongoEntity</code> annotation to your entity if you need to customize the name of the collection, the database, or the client.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@MongoEntity(collection="ThePerson")
public class Person  {
    public ObjectId id; // used by MongoDB for the _id field
    public String name;
    public LocalDate birth;
    public Status status;
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Annotating with <code>@MongoEntity</code> is optional. Here the entity will be stored in the <code>ThePerson</code> collection instead of the default <code>Person</code> collection.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>MongoDB with Panache uses the <a href="https://mongodb.github.io/mongo-java-driver/3.11/bson/pojos/">PojoCodecProvider</a> to map your entities to a MongoDB <code>Document</code>.</p>
</div>
<div class="paragraph">
<p>You will be allowed to use the following annotations to customize this mapping:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>@BsonId</code>: allows you to customize the ID field, see <a href="#custom-ids">Custom IDs</a>.</p>
</li>
<li>
<p><code>@BsonProperty</code>: customize the serialized name of the field.</p>
</li>
<li>
<p><code>@BsonIgnore</code>: ignore a field during the serialization.</p>
</li>
</ul>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
You can use public fields or private fields with getters/setters.
If you don&#8217;t want to manage the ID by yourself, you can make your entity extends <code>PanacheMongoEntity</code>.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="defining-your-repository"><a class="anchor" href="#defining-your-repository"></a>Defining your repository</h3>
<div class="paragraph">
<p>When using Repositories, you can get the exact same convenient methods as wit the active record pattern, injected in your Repository,
by making them implements <code>PanacheMongoRepository</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class PersonRepository implements PanacheMongoRepository&lt;Person&gt; {

   // put your custom logic here as instance methods

   public Person findByName(String name){
       return find("name", name).firstResult();
   }

   public List&lt;Person&gt; findAlive(){
       return list("status", Status.Alive);
   }

   public void deleteLoics(){
       delete("name", "Loïc");
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>All the operations that are defined on <code>PanacheMongoEntityBase</code> are available on your repository, so using it
is exactly the same as using the active record pattern, except you need to inject it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Inject
PersonRepository personRepository;

@GET
public long count(){
    return personRepository.count();
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="most-useful-operations-2"><a class="anchor" href="#most-useful-operations-2"></a>Most useful operations</h3>
<div class="paragraph">
<p>Once you have written your repository, here are the most common operations you will be able to perform:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// creating a person
Person person = new Person();
person.name = "Loïc";
person.birth = LocalDate.of(1910, Month.FEBRUARY, 1);
person.status = Status.Alive;

// persist it
personRepository.persist(person);

person.status = Status.Dead;

// Your must call update() in order to send your entity modifications to MongoDB
personRepository.update(person);

// delete it
personRepository.delete(person);

// getting a list of all Person entities
List&lt;Person&gt; allPersons = personRepository.listAll();

// finding a specific person by ID
person = personRepository.findById(personId);

// finding a specific person by ID via an Optional
Optional&lt;Person&gt; optional = personRepository.findByIdOptional(personId);
person = optional.orElseThrow(() -&gt; new NotFoundException());

// finding all living persons
List&lt;Person&gt; livingPersons = personRepository.list("status", Status.Alive);

// counting all persons
long countAll = personRepository.count();

// counting all living persons
long countAlive = personRepository.count("status", Status.Alive);

// delete all living persons
personRepository.delete("status", Status.Alive);

// delete all persons
personRepository.deleteAll();

// delete by id
boolean deleted = personRepository.deleteById(personId);

// set the name of all living persons to 'Mortal'
long updated = personRepository.update("name", "Mortal").where("status", Status.Alive);</code></pre>
</div>
</div>
<div class="paragraph">
<p>All <code>list</code> methods have equivalent <code>stream</code> versions.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">Stream&lt;Person&gt; persons = personRepository.streamAll();
List&lt;String&gt; namesButEmmanuels = persons
    .map(p -&gt; p.name.toLowerCase() )
    .filter( n -&gt; ! "emmanuel".equals(n) )
    .collect(Collectors.toList());</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
A <code>persistOrUpdate()</code> method exist that persist or update an entity in the database, it uses the <em>upsert</em> capability of MongoDB to do it in a single query.
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The rest of the documentation show usages based on the active record pattern only,
but keep in mind that they can be performed with the repository pattern as well.
The repository pattern examples have been omitted for brevity.
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="advanced-query"><a class="anchor" href="#advanced-query"></a>Advanced Query</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="paging"><a class="anchor" href="#paging"></a>Paging</h3>
<div class="paragraph">
<p>You should only use <code>list</code> and <code>stream</code> methods if your collection contains small enough data sets. For larger data
sets you can use the <code>find</code> method equivalents, which return a <code>PanacheQuery</code> on which you can do paging:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// create a query for all living persons
PanacheQuery&lt;Person&gt; livingPersons = Person.find("status", Status.Alive);

// make it use pages of 25 entries at a time
livingPersons.page(Page.ofSize(25));

// get the first page
List&lt;Person&gt; firstPage = livingPersons.list();

// get the second page
List&lt;Person&gt; secondPage = livingPersons.nextPage().list();

// get page 7
List&lt;Person&gt; page7 = livingPersons.page(Page.of(7, 25)).list();

// get the number of pages
int numberOfPages = livingPersons.pageCount();

// get the total number of entities returned by this query without paging
int count = livingPersons.count();

// and you can chain methods of course
return Person.find("status", Status.Alive)
    .page(Page.ofSize(25))
    .nextPage()
    .stream()</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>PanacheQuery</code> type has many other methods to deal with paging and returning streams.</p>
</div>
</div>
<div class="sect2">
<h3 id="using-a-range-instead-of-pages"><a class="anchor" href="#using-a-range-instead-of-pages"></a>Using a range instead of pages</h3>
<div class="paragraph">
<p><code>PanacheQuery</code> also allows range-based queries.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// create a query for all living persons
PanacheQuery&lt;Person&gt; livingPersons = Person.find("status", Status.Alive);

// make it use a range: start at index 0 until index 24 (inclusive).
livingPersons.range(0, 24);

// get the range
List&lt;Person&gt; firstRange = livingPersons.list();

// to get the next range, you need to call range again
List&lt;Person&gt; secondRange = livingPersons.range(25, 49).list();</code></pre>
</div>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You cannot mix ranges and pages: if you use a range, all methods that depend on having a current page will throw an <code>UnsupportedOperationException</code>;
you can switch back to paging using <code>page(Page)</code> or <code>page(int, int)</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="sorting"><a class="anchor" href="#sorting"></a>Sorting</h3>
<div class="paragraph">
<p>All methods accepting a query string also accept an optional <code>Sort</code> parameter, which allows you to abstract your sorting:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">List&lt;Person&gt; persons = Person.list(Sort.by("name").and("birth"));

// and with more restrictions
List&lt;Person&gt; persons = Person.list("status", Sort.by("name").and("birth"), Status.Alive);</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>Sort</code> class has plenty of methods for adding columns and specifying sort direction.</p>
</div>
</div>
<div class="sect2">
<h3 id="simplified-queries"><a class="anchor" href="#simplified-queries"></a>Simplified queries</h3>
<div class="paragraph">
<p>Normally, MongoDB queries are of this form: <code>{'firstname': 'John', 'lastname':'Doe'}</code>, this is what we call MongoDB native queries.</p>
</div>
<div class="paragraph">
<p>You can use them if you want, but we also support what we call <strong>PanacheQL</strong> that can be seen as a subset of <a href="https://docs.oracle.com/javaee/7/tutorial/persistence-querylanguage.htm#BNBTG">JPQL</a> (or <a href="https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#hql">HQL</a>) and allows you to easily express a query.
MongoDB with Panache will then map it to a MongoDB native query.</p>
</div>
<div class="paragraph">
<p>If your query does not start with <code>{</code>, we will consider it a PanacheQL query:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>&lt;singlePropertyName&gt;</code> (and single parameter) which will expand to <code>{'singleColumnName': '?1'}</code></p>
</li>
<li>
<p><code>&lt;query&gt;</code> will expand to <code>{&lt;query&gt;}</code> where we will map the PanacheQL query to MongoDB native query form. We support the following operators that will be mapped to the corresponding MongoDB operators: 'and', 'or' ( mixing 'and' and 'or' is not currently supported), '=', '&gt;', '&gt;=', '&lt;', '&#8656;', '!=', 'is null', 'is not null', and 'like' that is mapped to the MongoDB <code>$regex</code> operator (both String and JavaScript patterns are supported).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Here are some query examples:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>firstname = ?1 and status = ?2</code> will be mapped to <code>{'firstname': ?1, 'status': ?2}</code></p>
</li>
<li>
<p><code>amount &gt; ?1 and firstname != ?2</code> will be mapped to <code>{'amount': {'$gt': ?1}, 'firstname': {'$ne': ?2}}</code></p>
</li>
<li>
<p><code>lastname like ?1</code> will be mapped to <code>{'lastname': {'$regex': ?1}}</code>. Be careful that this will be <a href="https://docs.mongodb.com/manual/reference/operator/query/regex/#op._S_regex">MongoDB regex</a> support and not SQL like pattern.</p>
</li>
<li>
<p><code>lastname is not null</code> will be mapped to <code>{'lastname':{'$exists': true}}</code></p>
</li>
<li>
<p><code>status in ?1</code> will be mapped to <code>{'status':{$in: [?1]}}</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>We also handle some basic date type transformations: all fields of type <code>Date</code>, <code>LocalDate</code>, <code>LocalDateTime</code> or <code>Instant</code> will be mapped to the
<a href="https://docs.mongodb.com/manual/reference/bson-types/#document-bson-type-date">BSON Date</a> using the <code>ISODate</code> type (UTC datetime).
The MongoDB POJO codec doesn&#8217;t support <code>ZonedDateTime</code> and <code>OffsetDateTime</code> so you should convert them prior usage.</p>
</div>
<div class="paragraph">
<p>MongoDB with Panache also supports extended MongoDB queries by providing a <code>Document</code> query, this is supported by the find/list/stream/count/delete methods.</p>
</div>
<div class="paragraph">
<p>MongoDB with Panache offers operations to update multiple documents based on an update document and a query :
<code>Person.update("foo = ?1, bar = ?2", fooName, barName).where("name = ?1", name)</code>.</p>
</div>
<div class="paragraph">
<p>For these operations, you can express the update document the same way you express your queries, here are some examples:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>&lt;singlePropertyName&gt;</code> (and single parameter) which will expand to the update document <code>{'$set' : {'singleColumnName': '?1'}}</code></p>
</li>
<li>
<p><code>firstname = ?1, status = ?2</code> will be mapped to the update document <code>{'$set' : {'firstname': ?1, 'status': ?2}}</code></p>
</li>
<li>
<p><code>firstname = :firstname, status = :status</code> will be mapped to the update document <code>{'$set' : {'firstname': :firstname, 'status': :status}}</code></p>
</li>
<li>
<p><code>{'firstname' : ?1, 'status' : ?2}</code> will be mapped to the update document <code>{'$set' : {'firstname': ?1, 'status': ?2}}</code></p>
</li>
<li>
<p><code>{'firstname' : firstname, 'status' : :status}</code> ` will be mapped to the update document <code>{'$set' : {'firstname': :firstname, 'status': :status}}</code></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="query-parameters"><a class="anchor" href="#query-parameters"></a>Query parameters</h3>
<div class="paragraph">
<p>You can pass query parameters, for both native and PanacheQL queries, by index (1-based) as shown below:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">Person.find("name = ?1 and status = ?2", "Loïc", Status.Alive);
Person.find("{'name': ?1, 'status': ?2}", "Loïc", Status.Alive);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or by name using a <code>Map</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();
params.put("name", "Loïc");
params.put("status", Status.Alive);
Person.find("name = :name and status = :status", params);
Person.find("{'name': :name, 'status', :status}", params);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or using the convenience class <code>Parameters</code> either as is or to build a <code>Map</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// generate a Map
Person.find("name = :name and status = :status",
         Parameters.with("name", "Loïc").and("status", Status.Alive).map());

// use it as-is
Person.find("{'name': :name, 'status': :status}",
         Parameters.with("name", "Loïc").and("status", Status.Alive));</code></pre>
</div>
</div>
<div class="paragraph">
<p>Every query operation accepts passing parameters by index (<code>Object&#8230;&#8203;</code>), or by name (<code>Map&lt;String,Object&gt;</code> or <code>Parameters</code>).</p>
</div>
<div class="paragraph">
<p>When you use query parameters, be careful that PanacheQL queries will refer to the Object parameters name but native queries will refer to MongoDB field names.</p>
</div>
<div class="paragraph">
<p>Imagine the following entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class Person extends PanacheMongoEntity {
    @BsonProperty("lastname")
    public String name;
    public LocalDate birth;
    public Status status;

    public static Person findByNameWithPanacheQLQuery(String name){
        return find("name", name).firstResult();
    }

    public static Person findByNameWithNativeQuery(String name){
        return find("{'lastname': ?1}", name).firstResult();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Both <code>findByNameWithPanacheQLQuery()</code> and <code>findByNameWithNativeQuery()</code> methods will return the same result but query written in PanacheQL
will use the entity field name: <code>name</code>, and native query will use the MongoDB field name: <code>lastname</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="query-projection"><a class="anchor" href="#query-projection"></a>Query projection</h3>
<div class="paragraph">
<p>Query projection can be done with the <code>project(Class)</code> method on the <code>PanacheQuery</code> object that is returned by the <code>find()</code> methods.</p>
</div>
<div class="paragraph">
<p>You can use it to restrict which fields will be returned by the database,
the ID field will always be returned, but it&#8217;s not mandatory to include it inside the projection class.</p>
</div>
<div class="paragraph">
<p>For this, you need to create a class (a POJO) that will only contain the projected fields.
This POJO needs to be annotated with <code>@ProjectionFor(Entity.class)</code> where <code>Entity</code> is the name of your entity class.
The field names, or getters, of the projection class will be used to restrict which properties will be loaded from the database.</p>
</div>
<div class="paragraph">
<p>Projection can be done for both PanacheQL and native queries.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import io.quarkus.mongodb.panache.ProjectionFor;
import org.bson.codecs.pojo.annotations.BsonProperty;

// using public fields
@ProjectionFor(Person.class)
public class PersonName {
    public String name;
}

// using getters
@ProjectionFor(Person.class)
public class PersonNameWithGetter {
    private String name;

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}

// only 'name' will be loaded from the database
PanacheQuery&lt;PersonName&gt; shortQuery = Person.find("status ", Status.Alive).project(PersonName.class);
PanacheQuery&lt;PersonName&gt; query = Person.find("'status': ?1", Status.Alive).project(PersonNameWithGetter.class);
PanacheQuery&lt;PersonName&gt; nativeQuery = Person.find("{'status': 'ALIVE'}", Status.Alive).project(PersonName.class);</code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
Using <code>@BsonProperty</code> is not needed to define custom column mappings, as the mappings from the entity class will be used.
</td>
</tr>
</table>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
You can have your projection class extends from another class. In this case, the parent class also needs to have use <code>@ProjectionFor</code> annotation.
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="query-debugging"><a class="anchor" href="#query-debugging"></a>Query debugging</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As MongoDB with Panache allows writing simplified queries, it is sometimes handy to log the generated native queries for debugging purpose.</p>
</div>
<div class="paragraph">
<p>This can be achieved by setting to DEBUG the following log category inside your <code>application.properties</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.log.category."io.quarkus.mongodb.panache.runtime".level=DEBUG</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="transactions"><a class="anchor" href="#transactions"></a>Transactions</h2>
<div class="sectionbody">
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
MongoDB offers ACID transactions since version 4.0. MongoDB with Panache doesn&#8217;t provide support for them.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="custom-ids"><a class="anchor" href="#custom-ids"></a>Custom IDs</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IDs are often a touchy subject. In MongoDB, they are usually auto-generated by the database with an <code>ObjectId</code> type.
In MongoDB with Panache the ID are defined by a field named <code>id</code> of the <code>org.bson.types.ObjectId</code> type,
but if you want ot customize them, once again we have you covered.</p>
</div>
<div class="paragraph">
<p>You can specify your own ID strategy by extending <code>PanacheMongoEntityBase</code> instead of <code>PanacheMongoEntity</code>. Then
you just declare whatever ID you want as a public field by annotating it by <code>@BsonId</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@MongoEntity
public class Person extends PanacheMongoEntityBase {

    @BsonId
    public Integer myId;

    //...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you&#8217;re using repositories, then you will want to extend <code>PanacheMongoRepositoryBase</code> instead of <code>PanacheMongoRepository</code>
and specify your ID type as an extra type parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class PersonRepository implements PanacheMongoRepositoryBase&lt;Person,Integer&gt; {
    //...
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>When using <code>ObjectId</code>, MongoDB will automatically provide a value for you, but if you use a custom field type,
you need to provide the value by yourself.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p><code>ObjectId</code> can be difficult to use if you want to expose its value in your REST service.
So we created JSON-B and Jackson providers to serialize/deserialize them as a <code>String</code> which are automatically registered if your project depends on either the RESTEasy JSON-B extension or the RESTEasy Jackson extension.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="working-with-kotlin-data-classes"><a class="anchor" href="#working-with-kotlin-data-classes"></a>Working with Kotlin Data classes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Kotlin data classes are a very convenient way of defining data carrier classes, making them a great match to define an entity class.</p>
</div>
<div class="paragraph">
<p>But this type of class comes with some limitations: all fields needs to be initialized at construction time or be marked as nullable,
and the generated constructor needs to have as parameters all the fields of the data class.</p>
</div>
<div class="paragraph">
<p>MongoDB with Panache uses the <code>PojoCodec</code>, a MongoDB codec which mandates the presence of a parameterless constructor.</p>
</div>
<div class="paragraph">
<p>Therefore, if you want to use a data class as an entity class, you need a way to make Kotlin generate an empty constructor.
To do so, you need to provide default values for all the fields of your classes.
The following sentence from the Kotlin documentation explains it:</p>
</div>
<div class="paragraph">
<p><em>On the JVM, if the generated class needs to have a parameterless constructor, default values for all properties have to be specified (see Constructors).</em></p>
</div>
<div class="paragraph">
<p>If for whatever reason, the aforementioned solution is deemed unacceptable, there are alternatives.</p>
</div>
<div class="paragraph">
<p>First, you can create a BSON Codec which will be automatically registered by Quarkus and will be used instead of the <code>PojoCodec</code>.
See this part of the documentation: <a href="mongodb#simplifying-mongodb-client-usage-using-bson-codec">Using BSON codec</a>.</p>
</div>
<div class="paragraph">
<p>Another option is to use the <code>@BsonCreator</code> annotation to tell the <code>PojoCodec</code> to use the Kotlin data class default constructor,
in this case all constructor parameters have to be annotated with <code>@BsonProperty</code>: see <a href="https://mongodb.github.io/mongo-java-driver/3.11/bson/pojos/#supporting-pojos-without-no-args-constructors">Supporting pojos without no args constructor</a>.</p>
</div>
<div class="paragraph">
<p>This will only work when the entity extends <code>PanacheMongoEntityBase</code> and not <code>PanacheMongoEntity</code>, as the ID field also needs to be included in the constructor.</p>
</div>
<div class="paragraph">
<p>An example of a <code>Person</code> class defined as a Kotlin data class would look like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="kotlin" class="language-kotlin hljs">data class Person @BsonCreator constructor (
    @BsonId var id: ObjectId,
    @BsonProperty("name") var name: String,
    @BsonProperty("birth") var birth: LocalDate,
    @BsonProperty("status") var status: Status
): PanacheMongoEntityBase()</code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Here we use <code>var</code> but note that <code>val</code> can also be used.</p>
</div>
<div class="paragraph">
<p>The <code>@BsonId</code> annotation is used instead of <code>@BsonProperty("_id")</code> for brevity&#8217;s sake, but use of either is valid.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The last option is to the use the <a href="https://kotlinlang.org/docs/reference/compiler-plugins.html#no-arg-compiler-plugin">no-arg</a> compiler plugin.
This plugin is configured with a list of annotations, and the end result is the generation of no-args constructor for each class annotated with them.</p>
</div>
<div class="paragraph">
<p>For MongoDB with Panache, you could use the <code>@MongoEntity</code> annotation on your data class for this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="kotlin" class="language-kotlin hljs">@MongoEntity
data class Person (
    var name: String,
    var birth: LocalDate,
    var status: Status
): PanacheMongoEntity()</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="reactive"><a class="anchor" href="#reactive"></a>Reactive Entities and Repositories</h2>
<div class="sectionbody">
<div class="paragraph">
<p>MongoDB with Panache allows using reactive style implementation for both entities and repositories.
For this, you need to use the Reactive variants when defining your entities : <code>ReactivePanacheMongoEntity</code> or <code>ReactivePanacheMongoEntityBase</code>,
and when defining your repositories: <code>ReactivePanacheMongoRepository</code> or <code>ReactivePanacheMongoRepositoryBase</code>.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="title">Mutiny</div>
<div class="paragraph">
<p>The reactive API of the MongoDB with Panache uses Mutiny reactive types, if you&#8217;re not familiar with them, read the <a href="getting-started-reactive#mutiny">Getting Started with Reactive guide</a> first.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The reactive variant of the <code>Person</code> class will be:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class ReactivePerson extends ReactivePanacheMongoEntity {
    public String name;
    public LocalDate birth;
    public Status status;

    // return name as uppercase in the model
    public String getName(){
        return name.toUpperCase();
    }

    // store all names in lowercase in the DB
    public void setName(String name){
        this.name = name.toLowerCase();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You will have access to the same functionalities of the <em>imperative</em> variant inside the reactive one: bson annotations, custom ID, PanacheQL, &#8230;&#8203;
But the methods on your entities or repositories will all return reactive types.</p>
</div>
<div class="paragraph">
<p>See the equivalent methods from the imperative example with the reactive variant:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">// creating a person
ReactivePerson person = new ReactivePerson();
person.name = "Loïc";
person.birth = LocalDate.of(1910, Month.FEBRUARY, 1);
person.status = Status.Alive;

// persist it
Uni&lt;Void&gt; cs1 = person.persist();

person.status = Status.Dead;

// Your must call update() in order to send your entity modifications to MongoDB
Uni&lt;Void&gt; cs2 = person.update();

// delete it
Uni&lt;Void&gt; cs3 = person.delete();

// getting a list of all persons
Uni&lt;List&lt;ReactivePerson&gt;&gt; allPersons = ReactivePerson.listAll();

// finding a specific person by ID
Uni&lt;ReactivePerson&gt; personById = ReactivePerson.findById(personId);

// finding a specific person by ID via an Optional
Uni&lt;Optional&lt;ReactivePerson&gt;&gt; optional = ReactivePerson.findByIdOptional(personId);
personById = optional.map(o -&gt; o.orElseThrow(() -&gt; new NotFoundException()));

// finding all living persons
Uni&lt;List&lt;ReactivePerson&gt;&gt; livingPersons = ReactivePerson.list("status", Status.Alive);

// counting all persons
Uni&lt;Long&gt; countAll = ReactivePerson.count();

// counting all living persons
Uni&lt;Long&gt; countAlive = ReactivePerson.count("status", Status.Alive);

// delete all living persons
Uni&lt;Long&gt;  deleteCount = ReactivePerson.delete("status", Status.Alive);

// delete all persons
deleteCount = ReactivePerson.deleteAll();

// delete by id
Uni&lt;Boolean&gt; deleted = ReactivePerson.deleteById(personId);

// set the name of all living persons to 'Mortal'
Uni&lt;Long&gt; updated = ReactivePerson.update("name", "Mortal").where("status", Status.Alive);</code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
If you use MongoDB with Panache in conjunction with RESTEasy, you can directly return a reactive type inside your JAX-RS resource endpoint as long as you include the <code>quarkus-resteasy-mutiny</code> extension.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The same query facility exists for the reactive types, but the <code>stream()</code> methods act differently: they return a <code>Multi</code> (which implement  a reactive stream <code>Publisher</code>) instead of a <code>Stream</code>.</p>
</div>
<div class="paragraph">
<p>It allows more advanced reactive use cases, for example, you can use it to send server-sent events (SSE) via RESTEasy:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import org.jboss.resteasy.annotations.SseElementType;
import org.reactivestreams.Publisher;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@GET
@Path("/stream")
@Produces(MediaType.SERVER_SENT_EVENTS)
@SseElementType(MediaType.APPLICATION_JSON)
public Multi&lt;ReactivePerson&gt; streamPersons() {
    return ReactivePerson.streamAll();
}</code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<code>@SseElementType(MediaType.APPLICATION_JSON)</code> tells RESTEasy to serialize the object in JSON.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="mocking"><a class="anchor" href="#mocking"></a>Mocking</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="using-the-active-record-pattern"><a class="anchor" href="#using-the-active-record-pattern"></a>Using the active-record pattern</h3>
<div class="paragraph">
<p>If you are using the active-record pattern you cannot use Mockito directly as it does not support mocking static methods,
but you can use the <code>quarkus-panache-mock</code> module which allows you to use Mockito to mock all provided static
methods, including your own.</p>
</div>
<div class="paragraph">
<p>Add this dependency to your <code>pom.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-panache-mock&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Given this simple entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class Person extends PanacheMongoEntity {

    public String name;

    public static List&lt;Person&gt; findOrdered() {
        return findAll(Sort.by("lastname", "firstname")).list();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can write your mocking test like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@QuarkusTest
public class PanacheFunctionalityTest {

    @Test
    public void testPanacheMocking() {
        PanacheMock.mock(Person.class);

        // Mocked classes always return a default value
        Assertions.assertEquals(0, Person.count());

        // Now let's specify the return value
        Mockito.when(Person.count()).thenReturn(23l);
        Assertions.assertEquals(23, Person.count());

        // Now let's change the return value
        Mockito.when(Person.count()).thenReturn(42l);
        Assertions.assertEquals(42, Person.count());

        // Now let's call the original method
        Mockito.when(Person.count()).thenCallRealMethod();
        Assertions.assertEquals(0, Person.count());

        // Check that we called it 4 times
        PanacheMock.verify(Person.class, Mockito.times(4)).count();<i class="conum" data-value="1"></i><b>(1)</b>

        // Mock only with specific parameters
        Person p = new Person();
        Mockito.when(Person.findById(12l)).thenReturn(p);
        Assertions.assertSame(p, Person.findById(12l));
        Assertions.assertNull(Person.findById(42l));

        // Mock throwing
        Mockito.when(Person.findById(12l)).thenThrow(new WebApplicationException());
        Assertions.assertThrows(WebApplicationException.class, () -&gt; Person.findById(12l));

        // We can even mock your custom methods
        Mockito.when(Person.findOrdered()).thenReturn(Collections.emptyList());
        Assertions.assertTrue(Person.findOrdered().isEmpty());

        PanacheMock.verify(Person.class).findOrdered();
        PanacheMock.verify(Person.class, Mockito.atLeastOnce()).findById(Mockito.any());
        PanacheMock.verifyNoMoreInteractions(Person.class);
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Be sure to call your <code>verify</code> methods on <code>PanacheMock</code> rather than <code>Mockito</code>, otherwise you won&#8217;t know
what mock object to pass.</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="using-the-repository-pattern"><a class="anchor" href="#using-the-repository-pattern"></a>Using the repository pattern</h3>
<div class="paragraph">
<p>If you are using the repository pattern you can use Mockito directly, using the <code>quarkus-junit5-mockito</code> module,
which makes mocking beans much easier:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-junit5-mockito&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Given this simple entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public class Person {

    @BsonId
    public Long id;

    public String name;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>And this repository:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class PersonRepository implements PanacheMongoRepository&lt;Person&gt; {
    public List&lt;Person&gt; findOrdered() {
        return findAll(Sort.by("lastname", "firstname")).list();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can write your mocking test like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@QuarkusTest
public class PanacheFunctionalityTest {
    @InjectMock
    PersonRepository personRepository;

    @Test
    public void testPanacheRepositoryMocking() throws Throwable {
        // Mocked classes always return a default value
        Assertions.assertEquals(0, personRepository.count());

        // Now let's specify the return value
        Mockito.when(personRepository.count()).thenReturn(23l);
        Assertions.assertEquals(23, personRepository.count());

        // Now let's change the return value
        Mockito.when(personRepository.count()).thenReturn(42l);
        Assertions.assertEquals(42, personRepository.count());

        // Now let's call the original method
        Mockito.when(personRepository.count()).thenCallRealMethod();
        Assertions.assertEquals(0, personRepository.count());

        // Check that we called it 4 times
        Mockito.verify(personRepository, Mockito.times(4)).count();

        // Mock only with specific parameters
        Person p = new Person();
        Mockito.when(personRepository.findById(12l)).thenReturn(p);
        Assertions.assertSame(p, personRepository.findById(12l));
        Assertions.assertNull(personRepository.findById(42l));

        // Mock throwing
        Mockito.when(personRepository.findById(12l)).thenThrow(new WebApplicationException());
        Assertions.assertThrows(WebApplicationException.class, () -&gt; personRepository.findById(12l));

        Mockito.when(personRepository.findOrdered()).thenReturn(Collections.emptyList());
        Assertions.assertTrue(personRepository.findOrdered().isEmpty());

        // We can even mock your custom methods
        Mockito.verify(personRepository).findOrdered();
        Mockito.verify(personRepository, Mockito.atLeastOnce()).findById(Mockito.any());
        Mockito.verifyNoMoreInteractions(personRepository);
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="how-and-why-we-simplify-mongodb-api"><a class="anchor" href="#how-and-why-we-simplify-mongodb-api"></a>How and why we simplify MongoDB API</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When it comes to writing MongoDB entities, there are a number of annoying things that users have grown used to
reluctantly deal with, such as:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Duplicating ID logic: most entities need an ID, most people don&#8217;t care how it&#8217;s set, because it&#8217;s not really
relevant to your model.</p>
</li>
<li>
<p>Dumb getters and setters: since Java lacks support for properties in the language, we have to create fields,
then generate getters and setters for those fields, even if they don&#8217;t actually do anything more than read/write
the fields.</p>
</li>
<li>
<p>Traditional EE patterns advise to split entity definition (the model) from the operations you can do on them
(DAOs, Repositories), but really that requires an unnatural split between the state and its operations even though
we would never do something like that for regular objects in the Object Oriented architecture, where state and methods are in the same class. Moreover, this requires two classes per entity, and requires injection of the DAO or Repository where you need to do entity operations, which breaks your edit flow and requires you to get out of the code you&#8217;re writing to set up an injection point before coming back to use it.</p>
</li>
<li>
<p>MongoDB queries are super powerful, but overly verbose for common operations, requiring you to write queries even
when you don&#8217;t need all the parts.</p>
</li>
<li>
<p>MongoDB queries are JSON based, so you will need some String manipulation or using the <code>Document</code> type and it will need a lot of boilerplate code.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>With Panache, we took an opinionated approach to tackle all these problems:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Make your entities extend <code>PanacheMongoEntity</code>: it has an ID field that is auto-generated. If you require
a custom ID strategy, you can extend <code>PanacheMongoEntityBase</code> instead and handle the ID yourself.</p>
</li>
<li>
<p>Use public fields. Get rid of dumb getter and setters. Under the hood, we will generate all getters and setters
that are missing, and rewrite every access to these fields to use the accessor methods. This way you can still
write <em>useful</em> accessors when you need them, which will be used even though your entity users still use field accesses.</p>
</li>
<li>
<p>With the active record pattern: put all your entity logic in static methods in your entity class and don&#8217;t create DAOs.
Your entity superclass comes with lots of super useful static methods, and you can add your own in your entity class.
Users can just start using your entity <code>Person</code> by typing <code>Person.</code> and getting completion for all the operations in a single place.</p>
</li>
<li>
<p>Don&#8217;t write parts of the query that you don&#8217;t need: write <code>Person.find("order by name")</code> or
<code>Person.find("name = ?1 and status = ?2", "Loïc", Status.Alive)</code> or even better <code>Person.find("name", "Loïc")</code>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>That&#8217;s all there is to it: with Panache, MongoDB has never looked so trim and neat.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="defining-entities-in-external-projects-or-jars"><a class="anchor" href="#defining-entities-in-external-projects-or-jars"></a>Defining entities in external projects or jars</h2>
<div class="sectionbody">
<div class="paragraph">
<p>MongoDB with Panache relies on compile-time bytecode enhancements to your entities.</p>
</div>
<div class="paragraph">
<p>It attempts to identity archives with Panache entities (and consumers of Panache entities)
by the presence of the marker file <code>META-INF/panache-archive.marker</code>. Panache includes an
annotation processor that will automatically create this file in archives that depend on
Panache (even indirectly). If you have disabled annotation processors you may need to create
this file manually in some cases.</p>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
